package com.pai4j.zwiki.service.agent;

import com.pai4j.zwiki.domain.entity.CodeStructureEntity;
import com.pai4j.zwiki.repository.CodeStructureRepository;
import com.pai4j.zwiki.service.LLMService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 代码执行流程追踪器
 * 
 * 核心功能：
 * 1. 追踪从Controller到Repository的完整调用链
 * 2. 识别关键的业务处理节点
 * 3. 分析数据在各层之间的流转和转换
 * 4. 识别事务边界和异常处理点
 * 5. 生成可视化的执行流程图
 * 6. 使用LLM深度理解业务流程
 *
 * @author pai4j
 * @since 2025-10-14
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CodeExecutionFlowTracer {

    private final CodeStructureRepository codeStructureRepository;
    private final LLMService llmService;

    /**
     * 追踪业务执行流程
     */
    public Map<String, Object> traceBusinessExecutionFlows(String taskId, String workspacePath) {
        log.info("开始追踪业务执行流程, 任务ID: {}", taskId);

        Map<String, Object> flowReport = new HashMap<>();

        try {
            List<CodeStructureEntity> structures = codeStructureRepository.findByTaskId(taskId);

            // 1. 识别所有的Controller方法（业务入口）
            log.info("1. 识别业务入口点");
            List<Map<String, Object>> entryPoints = identifyEntryPoints(structures, workspacePath);
            flowReport.put("entryPoints", entryPoints);

            // 2. 追踪每个入口的执行流程
            log.info("2. 追踪执行流程");
            List<Map<String, Object>> flows = new ArrayList<>();
            
            for (Map<String, Object> entryPoint : entryPoints.stream().limit(10).collect(Collectors.toList())) {
                Map<String, Object> flow = traceFlowFromEntry(entryPoint, structures, workspacePath);
                flows.add(flow);
            }
            flowReport.put("executionFlows", flows);

            // 3. 识别关键数据转换点
            log.info("3. 识别数据转换点");
            List<Map<String, Object>> transformationPoints = identifyDataTransformationPoints(flows);
            flowReport.put("transformationPoints", transformationPoints);

            // 4. 识别事务边界
            log.info("4. 识别事务边界");
            List<Map<String, Object>> transactionBoundaries = identifyTransactionBoundaries(flows, structures);
            flowReport.put("transactionBoundaries", transactionBoundaries);

            // 5. 使用LLM分析执行流程
            log.info("5. LLM分析执行流程");
            String flowAnalysis = analyzeFlowsWithLLM(flowReport);
            flowReport.put("llmFlowAnalysis", flowAnalysis);

            log.info("业务执行流程追踪完成");

        } catch (Exception e) {
            log.error("追踪执行流程失败", e);
            flowReport.put("error", e.getMessage());
        }

        return flowReport;
    }

    /**
     * 识别业务入口点（Controller方法）
     */
    private List<Map<String, Object>> identifyEntryPoints(List<CodeStructureEntity> structures, 
                                                          String workspacePath) {
        List<Map<String, Object>> entryPoints = new ArrayList<>();

        List<CodeStructureEntity> controllers = structures.stream()
                .filter(s -> s.getName().endsWith("Controller"))
                .collect(Collectors.toList());

        for (CodeStructureEntity controller : controllers) {
            try {
                Path filePath = Paths.get(controller.getFilePath());
                if (!Files.exists(filePath)) continue;

                String code = Files.readString(filePath);

                // 提取所有的@RequestMapping方法
                List<Map<String, Object>> methods = extractControllerMethods(code, controller.getName());
                entryPoints.addAll(methods);

            } catch (Exception e) {
                log.warn("提取Controller方法失败: {}", controller.getName(), e);
            }
        }

        return entryPoints;
    }

    /**
     * 提取Controller方法
     */
    private List<Map<String, Object>> extractControllerMethods(String code, String controllerName) {
        List<Map<String, Object>> methods = new ArrayList<>();

        // 匹配@RequestMapping、@GetMapping、@PostMapping等
        Pattern pattern = Pattern.compile(
                "@(GetMapping|PostMapping|PutMapping|DeleteMapping|RequestMapping)\\s*\\([^)]*\\)\\s+" +
                "public\\s+\\S+\\s+(\\w+)\\s*\\([^)]*\\)",
                Pattern.MULTILINE
        );

        Matcher matcher = pattern.matcher(code);

        while (matcher.find()) {
            Map<String, Object> method = new HashMap<>();
            method.put("controller", controllerName);
            method.put("httpMethod", matcher.group(1));
            method.put("methodName", matcher.group(2));
            method.put("fullSignature", matcher.group(0));
            
            methods.add(method);
        }

        return methods;
    }

    /**
     * 追踪单个入口的执行流程
     */
    private Map<String, Object> traceFlowFromEntry(Map<String, Object> entryPoint,
                                                     List<CodeStructureEntity> structures,
                                                     String workspacePath) {
        Map<String, Object> flow = new HashMap<>();
        flow.put("entryPoint", entryPoint);

        try {
            String controllerName = (String) entryPoint.get("controller");
            String methodName = (String) entryPoint.get("methodName");

            // 查找Controller类
            Optional<CodeStructureEntity> controllerOpt = structures.stream()
                    .filter(s -> s.getName().equals(controllerName))
                    .findFirst();

            if (controllerOpt.isEmpty()) {
                return flow;
            }

            CodeStructureEntity controller = controllerOpt.get();
            String code = Files.readString(Paths.get(controller.getFilePath()));

            // 提取方法体
            String methodBody = extractMethodBody(code, methodName);
            
            if (methodBody != null) {
                // 识别调用的Service方法
                List<String> serviceCalls = identifyServiceCalls(methodBody);
                flow.put("serviceCalls", serviceCalls);

                // 追踪Service层
                List<Map<String, Object>> serviceFlows = new ArrayList<>();
                for (String serviceCall : serviceCalls.stream().limit(5).collect(Collectors.toList())) {
                    Map<String, Object> serviceFlow = traceServiceCall(serviceCall, structures, workspacePath);
                    serviceFlows.add(serviceFlow);
                }
                flow.put("serviceFlows", serviceFlows);

                // 构建完整的调用链
                List<String> callChain = buildCallChain(flow);
                flow.put("callChain", callChain);
            }

        } catch (Exception e) {
            log.warn("追踪流程失败: {}", entryPoint, e);
            flow.put("error", e.getMessage());
        }

        return flow;
    }

    /**
     * 提取方法体
     */
    private String extractMethodBody(String code, String methodName) {
        // 简化实现：查找方法定义并提取到方法结束
        int methodStart = code.indexOf("public ") + code.substring(code.indexOf("public ")).indexOf(methodName);
        if (methodStart < 0) return null;

        int braceCount = 0;
        int bodyStart = code.indexOf('{', methodStart);
        if (bodyStart < 0) return null;

        int bodyEnd = bodyStart;
        for (int i = bodyStart; i < code.length(); i++) {
            if (code.charAt(i) == '{') braceCount++;
            if (code.charAt(i) == '}') braceCount--;
            if (braceCount == 0) {
                bodyEnd = i;
                break;
            }
        }

        return code.substring(bodyStart, bodyEnd + 1);
    }

    /**
     * 识别Service调用
     */
    private List<String> identifyServiceCalls(String methodBody) {
        List<String> calls = new ArrayList<>();

        // 匹配 serviceVariable.methodName() 模式
        Pattern pattern = Pattern.compile("(\\w+Service)\\.{1,}(\\w+)\\s*\\(");
        Matcher matcher = pattern.matcher(methodBody);

        while (matcher.find()) {
            String call = matcher.group(1) + "." + matcher.group(2) + "()";
            calls.add(call);
        }

        return calls;
    }

    /**
     * 追踪Service调用
     */
    private Map<String, Object> traceServiceCall(String serviceCall, 
                                                   List<CodeStructureEntity> structures,
                                                   String workspacePath) {
        Map<String, Object> serviceFlow = new HashMap<>();
        serviceFlow.put("call", serviceCall);

        try {
            // 解析服务名和方法名
            String[] parts = serviceCall.split("\\.");
            if (parts.length < 2) return serviceFlow;

            String serviceName = parts[0];
            
            // 查找Service类
            Optional<CodeStructureEntity> serviceOpt = structures.stream()
                    .filter(s -> s.getName().contains(serviceName))
                    .findFirst();

            if (serviceOpt.isPresent()) {
                serviceFlow.put("serviceName", serviceOpt.get().getName());
                serviceFlow.put("package", serviceOpt.get().getPackageName());
                
                // 识别Repository调用
                String code = Files.readString(Paths.get(serviceOpt.get().getFilePath()));
                List<String> repositoryCalls = identifyRepositoryCalls(code);
                serviceFlow.put("repositoryCalls", repositoryCalls);
            }

        } catch (Exception e) {
            log.warn("追踪Service调用失败: {}", serviceCall, e);
        }

        return serviceFlow;
    }

    /**
     * 识别Repository调用
     */
    private List<String> identifyRepositoryCalls(String code) {
        List<String> calls = new ArrayList<>();

        Pattern pattern = Pattern.compile("(\\w+Repository)\\.{1,}(\\w+)\\s*\\(");
        Matcher matcher = pattern.matcher(code);

        while (matcher.find()) {
            String call = matcher.group(1) + "." + matcher.group(2) + "()";
            calls.add(call);
        }

        return calls;
    }

    /**
     * 构建完整调用链
     */
    private List<String> buildCallChain(Map<String, Object> flow) {
        List<String> chain = new ArrayList<>();

        // 添加Controller
        @SuppressWarnings("unchecked")
        Map<String, Object> entryPoint = (Map<String, Object>) flow.get("entryPoint");
        chain.add(entryPoint.get("controller") + "." + entryPoint.get("methodName") + "()");

        // 添加Service
        @SuppressWarnings("unchecked")
        List<Map<String, Object>> serviceFlows = 
                (List<Map<String, Object>>) flow.get("serviceFlows");
        
        if (serviceFlows != null) {
            for (Map<String, Object> serviceFlow : serviceFlows) {
                chain.add((String) serviceFlow.get("call"));
                
                // 添加Repository
                @SuppressWarnings("unchecked")
                List<String> repoCalls = (List<String>) serviceFlow.get("repositoryCalls");
                if (repoCalls != null && !repoCalls.isEmpty()) {
                    chain.addAll(repoCalls);
                }
            }
        }

        return chain;
    }

    /**
     * 识别数据转换点
     */
    private List<Map<String, Object>> identifyDataTransformationPoints(List<Map<String, Object>> flows) {
        List<Map<String, Object>> transformations = new ArrayList<>();

        for (Map<String, Object> flow : flows) {
            // 分析每个流程中的数据转换
            // 简化实现：标记可能的转换点
            Map<String, Object> transformation = new HashMap<>();
            transformation.put("flow", flow.get("entryPoint"));
            transformation.put("transformationTypes", Arrays.asList(
                    "DTO → Entity", 
                    "Entity → VO",
                    "Request → Domain"
            ));
            transformations.add(transformation);
        }

        return transformations;
    }

    /**
     * 识别事务边界
     */
    private List<Map<String, Object>> identifyTransactionBoundaries(
            List<Map<String, Object>> flows,
            List<CodeStructureEntity> structures) {
        
        List<Map<String, Object>> boundaries = new ArrayList<>();

        // 查找带@Transactional注解的Service方法
        for (CodeStructureEntity structure : structures) {
            if (structure.getName().endsWith("Service")) {
                try {
                    String code = Files.readString(Paths.get(structure.getFilePath()));
                    if (code.contains("@Transactional")) {
                        Map<String, Object> boundary = new HashMap<>();
                        boundary.put("service", structure.getName());
                        boundary.put("package", structure.getPackageName());
                        boundary.put("hasTransaction", true);
                        boundaries.add(boundary);
                    }
                } catch (Exception e) {
                    log.warn("检查事务边界失败: {}", structure.getName(), e);
                }
            }
        }

        return boundaries;
    }

    /**
     * 使用LLM分析执行流程
     */
    private String analyzeFlowsWithLLM(Map<String, Object> flowReport) {
        StringBuilder prompt = new StringBuilder();
        prompt.append("请深入分析以下业务执行流程：\n\n");

        // 入口点信息
        @SuppressWarnings("unchecked")
        List<Map<String, Object>> entryPoints = (List<Map<String, Object>>) flowReport.get("entryPoints");
        if (entryPoints != null && !entryPoints.isEmpty()) {
            prompt.append("## 业务入口（Controller接口）\n\n");
            entryPoints.stream().limit(10).forEach(ep -> {
                prompt.append(String.format("- %s.%s() - %s\n", 
                        ep.get("controller"), ep.get("methodName"), ep.get("httpMethod")));
            });
            prompt.append("\n");
        }

        // 执行流程
        @SuppressWarnings("unchecked")
        List<Map<String, Object>> flows = (List<Map<String, Object>>) flowReport.get("executionFlows");
        if (flows != null && !flows.isEmpty()) {
            prompt.append("## 典型执行流程\n\n");
            flows.stream().limit(5).forEach(flow -> {
                @SuppressWarnings("unchecked")
                List<String> callChain = (List<String>) flow.get("callChain");
                if (callChain != null && !callChain.isEmpty()) {
                    prompt.append("### 流程示例\n");
                    prompt.append(String.join(" → ", callChain)).append("\n\n");
                }
            });
        }

        // 事务边界
        @SuppressWarnings("unchecked")
        List<Map<String, Object>> transactions = (List<Map<String, Object>>) flowReport.get("transactionBoundaries");
        if (transactions != null && !transactions.isEmpty()) {
            prompt.append("## 事务边界\n\n");
            transactions.stream().limit(10).forEach(tx -> {
                prompt.append(String.format("- %s\n", tx.get("service")));
            });
            prompt.append("\n");
        }

        prompt.append("""
                ---
                
                请分析：
                
                ## 1. 业务流程理解（30%）
                - 从入口到数据库，业务数据是如何流转的？
                - 每一层做了什么处理？
                - 数据是如何被转换的？（DTO → Entity → VO）
                
                ## 2. 架构分析（25%）
                - 这些流程体现了什么架构模式？
                - 分层是否清晰？职责是否分明？
                - 是否遵循了依赖倒置原则？
                
                ## 3. 事务管理（20%）
                - 事务边界设置是否合理？
                - 是否有事务传播的问题？
                - 事务的粒度是否适当？
                
                ## 4. 异常处理（15%）
                - 异常处理是否完善？
                - 是否有统一的异常处理机制？
                
                ## 5. 优化建议（10%）
                - 执行流程有哪些可以优化的地方？
                - 是否存在冗余的调用？
                - 如何提升性能？
                
                请详细分析（1000-1500字）。
                """);

        try {
            return llmService.generateCodeSummary(prompt.toString());
        } catch (Exception e) {
            log.error("LLM分析执行流程失败", e);
            return "流程分析失败: " + e.getMessage();
        }
    }
}

